#ifndef _DOFS_
#define _DOFS_

#include "Point.h"
/**
 * @brief  继承点类，增加全局编号
 */
template <unsigned int DIM>
class Dofs
{
public:
    /**
     * @brief 默认构造函数
     */
    Dofs() = default;
    Dofs(const Point<DIM> &_point, int _global_index = 0) : point{_point}, globalIndex{_global_index} {};
    Dofs(Point<DIM> &&_point, int _global_index = 0) : point{std::move(_point)}, globalIndex{_global_index} {};
    const Point<DIM> &getPoint() const;
    void setPoint(const Point<DIM> &_point);
    /**
     *@brief 默认析构函数
     */
    ~Dofs() = default;

    /**
     * @brief 设置全局编号。
     *
     * @param i:全局编号
     */
    void setGlobalIndex(const int i)
    {
        globalIndex = i;
    }
    /**
     * @brief 获取全局编号。
     *
     *
     * @return 全局编号。
     */
    int getGlobalIndex() const
    {
        return globalIndex;
    }
    /**
     * @brief 重载[]操作符
     *
     * @param d:第d个维度
     *
     * @return 第d个维度的坐标
     */
    const double &operator[](const unsigned int d) const
    {
        return point[d];
    }
    /**
     * @brief 友元函数，重载<<操作符
     *
     * @param os: ostream
     * @param dof: Dofs<D>&
     *
     * @return
     */
    template <unsigned int D>
    friend std::ostream &operator<<(std::ostream &os, const Dofs<D> &dof);

    template <unsigned int D>
    friend bool operator<(const Dofs<D> &dof1, const Dofs<D> &dof2);

    template <unsigned int D>
    friend bool operator>(const Dofs<D> &dof1, const Dofs<D> &dof2);

    template <unsigned int D>
    friend bool operator==(const Dofs<D> &dof1, const Dofs<D> &dof2);

    template <unsigned int D>
    friend bool operator<=(const Dofs<D> &dof1, const Dofs<D> &dof2);

    template <unsigned int D>
    friend bool operator>=(const Dofs<D> &dof1, const Dofs<D> &dof2);

private:
    Point<DIM> point;
    int globalIndex; /**<全局编号  */
};

template <unsigned int D>
std::ostream &operator<<(std::ostream &os, const Dofs<D> &dof)
{
    os << dof.globalIndex << " : ";
    os << "( ";
    for (unsigned int d = 0; d < D - 1; d++)
    {
        os << dof.point[d] << " , ";
    }
    os << dof.point[D - 1] << " )";
    return os;
}

template <unsigned int D>
bool operator<(const Dofs<D> &dof1, const Dofs<D> &dof2)
{
    if (dof1.getGlobalIndex() < dof2.getGlobalIndex())
        return true;
    else
        return false;
}

template <unsigned int D>
bool operator>(const Dofs<D> &dof1, const Dofs<D> &dof2)
{
    if (dof1.getGlobalIndex() > dof2.getGlobalIndex())
        return 1;
    else
        return 0;
}

template <unsigned int D>
bool operator==(const Dofs<D> &dof1, const Dofs<D> &dof2)
{
    if (dof1.getGlobalIndex() == dof2.getGlobalIndex())
        return 1;
    else
        return 0;
}

template <unsigned int D>
bool operator<=(const Dofs<D> &dof1, const Dofs<D> &dof2)
{
    if (dof1.getGlobalIndex() <= dof2.getGlobalIndex())
        return 1;
    else
        return 0;
}

template <unsigned int D>
bool operator>=(const Dofs<D> &dof1, const Dofs<D> &dof2)
{
    if (dof1.getGlobalIndex() >= dof2.getGlobalIndex())
        return 1;
    else
        return 0;
}
#else
// Do Nothing
#endif
